//***************************************************************************************
// Effects.h by X_Jun(MKXJun) (C) 2018-2020 All Rights Reserved.
// Licensed under the MIT License.
//
// 简易特效管理框架
// Simple effect management framework.
//***************************************************************************************

#ifndef EFFECTS_H
#define EFFECTS_H

#include <memory>
//#include "LightHelper.h"

#include <DirectXMath.h>
#include "GDxVertex.h"
#include <GGenericInfra/GMath.h>
#include <GRendererInfra\GRiLight.h>
#include <GRendererInfra\GRiObj.h>

#define  NUM_GBUFFER  4
struct SpotLight
{
	DirectX::XMFLOAT4 ambient;
	DirectX::XMFLOAT4 diffuse;
	DirectX::XMFLOAT4 specular;

	// 打包成4D向量: (position, range)
	DirectX::XMFLOAT3 position;
	float range;

	// 打包成4D向量: (direction, spot)
	DirectX::XMFLOAT3 direction;
	float spot;

	// 打包成4D向量: (att, pad)
	DirectX::XMFLOAT3 att;
	float pad; // 最后用一个浮点数填充使得该结构体大小满足16的倍数，便于我们以后在HLSL设置数组
};
struct DirectionalLight
{
	DirectX::XMFLOAT4 ambient;
	DirectX::XMFLOAT4 diffuse;
	DirectX::XMFLOAT4 specular;
	DirectX::XMFLOAT3 direction;
	float pad; // 最后用一个浮点数填充使得该结构体大小满足16的倍数，便于我们以后在HLSL设置数组
};
struct PointLight
{
	PointLight() { memset(this, 0, sizeof(PointLight)); }
	GMath::Vector3 Color;
	float Intensity;
	GMath::Vector3 Position;
	float Range;
};

struct Material
{
	GMath::Vector4 kd;
	GMath::Vector4 ka;
	GMath::Vector4 ks; // w = 镜面反射强度
};
class IEffect
{
public:
	// 使用模板别名(C++11)简化类型名
	template <class T>
	using ComPtr = Microsoft::WRL::ComPtr<T>;

	IEffect() = default;
	virtual ~IEffect() = default;
	// 不允许拷贝，允许移动
	IEffect(const IEffect&) = delete;
	IEffect& operator=(const IEffect&) = delete;
	IEffect(IEffect&&) = default;
	IEffect& operator=(IEffect&&) = default;

	// 更新并绑定常量缓冲区
	virtual void Apply(ID3D11DeviceContext * deviceContext) = 0;
};

class ISetObjEffect
{
public:
	virtual void XM_CALLCONV SetWorldMatrix(DirectX::FXMMATRIX W) = 0;

};
class ISetSubMeshEffect
{
public:
	virtual void SetTextureDiffuse(ID3D11ShaderResourceView* textureDiffuse) = 0;

	virtual void SetTextureBump(ID3D11ShaderResourceView* textureBump) = 0;

	virtual void SetTextureORM(ID3D11ShaderResourceView* textureOrm) = 0;

	virtual void SetMaterial(const Material& material) = 0;
};
class BasicEffect : public IEffect,public ISetObjEffect,public ISetSubMeshEffect
{
public:

	BasicEffect();
	virtual ~BasicEffect() override;

	BasicEffect(BasicEffect&& moveFrom) noexcept;
	BasicEffect& operator=(BasicEffect&& moveFrom) noexcept;

	// 获取单例
	static BasicEffect& Get();

	

	// 初始化所需资源
	bool InitAll(ID3D11Device * device);


	//
	// 渲染模式的变更
	//

	// 默认状态来绘制
	void SetRenderDefault(ID3D11DeviceContext * deviceContext);
	
	void SetGBufferPass(ID3D11DeviceContext* deviceContext);
	//
	// 矩阵设置
	//
	void SetId(int id) ;
	void SetFlag(int flag);
	void XM_CALLCONV SetWorldMatrix(std::array<float,16> W);
	virtual void XM_CALLCONV SetWorldMatrix(DirectX::FXMMATRIX W) override;
	void XM_CALLCONV SetViewMatrix(DirectX::FXMMATRIX V);
	void XM_CALLCONV SetProjMatrix(DirectX::FXMMATRIX P);


	//
	// 光照、材质和纹理相关设置
	//

	// 各种类型灯光允许的最大数目
	#define MAX_POINT_LIGHT_NUM 10
// 
	void SetLight(size_t pos, GUSPtr<GRiObj> pLight);
	void SetDirLight(size_t pos, const DirectionalLight& dirLight);
 	void SetPointLight(size_t pos, const PointLight& pointLight);
// 	void SetSpotLight(size_t pos, const SpotLight& spotLight);
// 
	virtual void SetMaterial(const Material& material) override;
	//void SetDir(const )

	virtual void SetTextureDiffuse(ID3D11ShaderResourceView * textureDiffuse)override;
	virtual void SetTextureBump(ID3D11ShaderResourceView* textureBump) override;
	virtual void SetTextureORM(ID3D11ShaderResourceView* textureOrm) override;

	void SetTexturesMainPass(ID3D11ShaderResourceView** textures);

	void XM_CALLCONV SetEyePos(DirectX::FXMVECTOR eyePos);

	//
	// 状态设置
	//
// 
// 	void SetFogState(bool isOn);
// 	void SetFogStart(float fogStart);
// 	void SetFogColor(DirectX::XMVECTOR fogColor);
// 	void SetFogRange(float fogRange);
	

	// 应用常量缓冲区和纹理资源的变更
	void Apply(ID3D11DeviceContext * deviceContext);
	
private:
	class Impl;
	std::unique_ptr<Impl> pImpl;
};


class SkyEffect : public IEffect
{
public:
	SkyEffect();
	virtual ~SkyEffect() override;

	SkyEffect(SkyEffect&& moveFrom) noexcept;
	SkyEffect& operator=(SkyEffect&& moveFrom) noexcept;

	// 获取单例
	static SkyEffect& Get();

	// 初始化所需资源
	bool InitAll(ID3D11Device* device);

	// 
	// 渲染模式的变更
	//

	// 默认状态来绘制
	void SetRenderDefault(ID3D11DeviceContext* deviceContext);

	//
	// 矩阵设置
	//
	void SetCorners(DirectX::XMFLOAT4X4 corners);
	//
	// 纹理立方体映射设置
	//
	void SetTextureCube(ID3D11ShaderResourceView* textureCube);

	// 应用常量缓冲区和纹理资源的变更
	void Apply(ID3D11DeviceContext* deviceContext);

private:
	class Impl;
	std::unique_ptr<Impl> pImpl;
};


class DebugEffect :public IEffect,public ISetObjEffect
{

	DebugEffect();
public:

	virtual ~DebugEffect() override;

	static DebugEffect& Get();

	bool InitAll(ID3D11Device* device);

	void SetRenderDefault(ID3D11DeviceContext* deviceContext);

	void SetTexture(ID3D11ShaderResourceView** texture);

	virtual void XM_CALLCONV SetWorldMatrix(DirectX::FXMMATRIX W) override;

	virtual void Apply(ID3D11DeviceContext* deviceContext) override;

private:
	class Impl;
	std::unique_ptr<Impl> pImpl;
};



#endif
